package services

import (
	"ez/apps/wms/conf"
	wms "ez/apps/wms/document"
	"gitee.com/dreamwood/ez-go/ez"
	"gitee.com/dreamwood/ez-go/ss"
	"gitee.com/dreamwood/ez-go/tools"
	"time"
)

func CreateChangeLog(itemId int64, ioType int64) {
	crud := wms.NewChangeLogCrud()
	start := tools.GetDayStart(time.Now())
	end := tools.GetDayEnd(time.Now())
	find, _ := crud.FindOneBy(ss.M{"itemId": itemId, "ioType": ioType, "createAt__gt": start, "createAt__lt": end}, nil)
	if find.Id > 0 {
		find.State = 0
	}
	find.ItemId = itemId
	find.IoType = ioType
	find.Save()
}

// CreateSummary 创建当前之前的汇总,不会有重复的冗余的操作，非实时
func CreateSummary() {
	crud := wms.NewChangeLogCrud()
	//只处理今天以前的信息
	dayStart := tools.GetDayStart(time.Now())
	rows, e := crud.FindBy(ss.M{"state": 0, "createAt__lt": dayStart}, []string{"id"}, 0, 10)
	//test
	//rows, e := crud.FindBy(ss.M{"state": 0}, []string{"id"}, 0, 10)
	if e != nil {
		return
	}
	for _, row := range rows {
		if row.IoType == conf.ChangeLogIn {
			SummaryInLog(row)
		}
		if row.IoType == conf.ChangeLogOut {
			SummaryOutLog(row)
		}
	}
}

// CreateSummaryManual 实时创建汇总，有物品重复出入库时会做无用功
func CreateSummaryManual() {
	crud := wms.NewChangeLogCrud()
	rows, e := crud.FindBy(ss.M{"state": 0}, []string{"id"}, 0, 100)
	if e != nil {
		return
	}
	for _, row := range rows {
		if row.IoType == conf.ChangeLogIn {
			SummaryInLog(row)
		}
		if row.IoType == conf.ChangeLogOut {
			SummaryOutLog(row)
		}
	}
}

func SummaryInLog(log *wms.ChangeLog) {
	crud := wms.NewInLogCrud()
	dayStart := time.Date(log.CreateAt.Year(), log.CreateAt.Month(), log.CreateAt.Day(), 0, 0, 0, 0, time.Local)
	dayEnd := time.Date(log.CreateAt.Year(), log.CreateAt.Month(), log.CreateAt.Day(), 24, 0, 0, 0, time.Local)
	//crudItemSku := wms.NewItemSkuCrud()
	//itemSku, _ := crudItemSku.Find(log.ItemId)
	rows, e := crud.FindBy(
		ss.M{
			"itemId":       log.ItemId,
			"createAt__gt": dayStart,
			"createAt__lt": dayEnd,
		},
		nil, 0, 0)
	if e != nil {
		return
	}
	toSave := make(map[int64]float64)
	toSaveWeight := make(map[int64]float64)
	for _, row := range rows {
		_, ok := toSave[row.TypeId]
		if !ok {
			toSave[row.TypeId] = 0
		}
		_, ok = toSaveWeight[row.TypeId]
		if !ok {
			toSaveWeight[row.TypeId] = 0
		}
		toSave[row.TypeId] += row.NumIn
		toSaveWeight[row.TypeId] += row.Cost
	}

	//汇总数据
	crudIOType := wms.NewIOTypeCrud()
	for id, sum := range toSave {
		y := log.CreateAt.Year()
		m := int(log.CreateAt.Month())
		d := log.CreateAt.Day()
		ymd := y*10000 + m*100 + d
		crudSummary := wms.NewSummaryCrud()
		//en := &wms.Summary{}
		en, _ := crudSummary.FindOneBy(ss.M{
			"ymd":    ymd,
			"itemId": log.ItemId,
			"typeId": id,
			"ioType": conf.ChangeLogIn,
		}, nil)
		en.ItemId = log.ItemId
		en.Num = sum
		en.Y = int64(y)
		en.M = int64(m)
		en.D = int64(d)
		en.Ymd = int64(ymd)
		en.IoType = conf.ChangeLogIn
		t, _ := crudIOType.FindId(id)
		en.TypeId = id
		en.TypeName = t.Name

		en.CreateAt = log.CreateAt
		en.SetEvent(true)
		_ = en.Save()
	}
	//更新ChangeLog
	log.State = 1
	//rst := tx.Select("State").Updates(log)
	log.SetEvent(true)
	log.Save()

}

func SummaryOutLog(log *wms.ChangeLog) {
	crud := wms.NewOutLogCrud()
	dayStart := time.Date(log.CreateAt.Year(), log.CreateAt.Month(), log.CreateAt.Day(), 0, 0, 0, 0, time.Local)
	dayEnd := time.Date(log.CreateAt.Year(), log.CreateAt.Month(), log.CreateAt.Day(), 24, 0, 0, 0, time.Local)
	rows, e := crud.FindBy(
		ss.M{
			"itemId":       log.ItemId,
			"createAt__gt": dayStart,
			"createAt__lt": dayEnd,
		},
		nil, 0, 0)
	if e != nil {
		return
	}
	toSave := make(map[int64]float64)
	toSaveWeight := make(map[int64]float64)
	for _, row := range rows {
		_, ok := toSave[row.TypeId]
		if !ok {
			toSave[row.TypeId] = 0
		}
		toSave[row.TypeId] += row.Num
		_, ok = toSaveWeight[row.TypeId]
		if !ok {
			toSaveWeight[row.TypeId] = 0
		}
		toSaveWeight[row.TypeId] += row.Cost
	}

	//汇总数据
	crudIOType := wms.NewIOTypeCrud()
	for id, sum := range toSave {

		y := log.CreateAt.Year()
		m := int(log.CreateAt.Month())
		d := log.CreateAt.Day()
		ymd := y*10000 + m*100 + d

		//en := &wms.Summary{}

		crudSummary := wms.NewSummaryCrud()
		//en := &wms.Summary{}
		en, _ := crudSummary.FindOneBy(ss.M{
			"ymd":    ymd,
			"itemId": log.ItemId,
			"typeId": id,
			"ioType": conf.ChangeLogOut,
		}, nil)
		en.ItemId = log.ItemId
		en.Num = sum
		en.Y = int64(y)
		en.M = int64(m)
		en.D = int64(d)
		en.Ymd = int64(ymd)
		en.IoType = conf.ChangeLogOut
		t, _ := crudIOType.FindId(id)
		en.TypeId = id
		en.TypeName = t.Name
		//now := time.Now()
		//en.CreateAt = &now
		en.CreateAt = log.CreateAt
		//rst := tx.Save(en)
		//if rst.Error != nil {
		//	return rst.Error
		//}
		en.SetEvent(true)
		en.Save()
	}
	//更新ChangeLog
	log.State = 1
	log.SetEvent(true)
	log.Save()
}

func GetSummaryRelatedItemIds(start time.Time, end time.Time) []struct {
	ItemId int64
} {
	relatedItemIds := make([]struct {
		ItemId int64
	}, 0)
	//db := global.DB
	//db.Model(&wms.Summary{}).
	//	Select("item_id").
	//	Group("item_id,item_name").
	//	Where("create_at > ?", start).
	//	Where("create_at < ?", end).
	//	Order("item_name asc").
	//	Find(&relatedItemIds)
	return relatedItemIds
}
func CreateSummaryTableData(start time.Time, end time.Time, itemIds ...int64) []*SummaryItemData {
	if len(itemIds) > 0 {
		//逐个获取汇总

		data := make([]*SummaryItemData, len(itemIds))
		for index, id := range itemIds {
			//生成项目的汇总数据
			//CreateSummaryForItem(row.ItemId,start,end)
			data[index] = CreateSummaryForItem(id, start, end, false)
		}
		return data
	} else {

		relatedItemIds := GetSummaryRelatedItemIds(start, end)
		//逐个获取汇总

		data := make([]*SummaryItemData, len(relatedItemIds))
		for index, row := range relatedItemIds {
			//生成项目的汇总数据
			//CreateSummaryForItem(row.ItemId,start,end)
			data[index] = CreateSummaryForItem(row.ItemId, start, end, false)
		}
		return data
	}
}
func CreateSummaryTableDataWeight(start time.Time, end time.Time, itemIds ...int64) []*SummaryItemData {
	if len(itemIds) > 0 {
		//逐个获取汇总

		data := make([]*SummaryItemData, len(itemIds))
		for index, id := range itemIds {
			//生成项目的汇总数据
			//CreateSummaryForItem(row.ItemId,start,end)
			data[index] = CreateSummaryForItem(id, start, end, true)
		}
		return data
	} else {

		relatedItemIds := GetSummaryRelatedItemIds(start, end)
		//逐个获取汇总

		data := make([]*SummaryItemData, len(relatedItemIds))
		for index, row := range relatedItemIds {
			//生成项目的汇总数据
			//CreateSummaryForItem(row.ItemId,start,end)
			data[index] = CreateSummaryForItem(row.ItemId, start, end, true)
		}
		return data
	}
}

type SummaryTableData struct {
	NumIn  float64
	NumOut float64
}

type SummaryItemData struct {
	Item *wms.ItemSku
	Cols map[int64]*SummaryTableData
}

func CreateSummaryForItem(itemId int64, start time.Time, end time.Time, isWeight bool) *SummaryItemData {

	crudItem := wms.NewItemSkuCrud()
	item, _ := crudItem.FindId(itemId)
	crud := wms.NewSummaryCrud()
	data := SummaryItemData{
		Item: item,
		Cols: map[int64]*SummaryTableData{},
	}

	rows, e := crud.FindBy(ss.M{"itemId": itemId, "createAt__gt": start, "createAt__lt": end}, nil, 0, 0)
	if e != nil {
		ez.PrintError(e)
		return nil
	}
	//ez.JsonLog(rows)

	for _, row := range rows {
		_, ok := data.Cols[row.Ymd]
		if !ok {
			data.Cols[row.Ymd] = &SummaryTableData{}
		}
		if row.IoType == conf.ChangeLogIn {
			if isWeight {
				//data.Cols[row.Ymd].NumIn += row.Weight
			} else {
				data.Cols[row.Ymd].NumIn += row.Num
			}
		}
		if row.IoType == conf.ChangeLogOut {
			if isWeight {
				//data.Cols[row.Ymd].NumOut += row.Weight
			} else {
				data.Cols[row.Ymd].NumOut += row.Num
			}
		}
	}
	return &data
}
